# textureclass by kejace 2005
# -*- coding: UTF-8 -*-

import Image
from OpenGL.GL import *
from OpenGLContext import texture
from cage import *
from random import *
import threading
from math import *
from polygon import *

class Billboard:
		
	def __init__(self,size=0):
		if size == 0:
			size = 2**randint(3,7)
		self.size = size
		self.image = Image.new('RGBA', (size,size),0)
		self.texture = None
		self.decalmode = GL_DECAL
		if randint(0,6) == 1:
			self.decalmode = GL_BLEND
		
	def make(self):
	
		self.texture = texture.Texture(self.image)
		
	def draw(self):

		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) # GL_NEAREST
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, self.decalmode)

		self.texture()

		glBegin(GL_QUADS)
		glTexCoord2f(0.0,0.0); glVertex3f(0.0, 0.0, 0.0)
		glTexCoord2f(1.0,0.0); glVertex3f(1.0,  0.0, 0.0)
		glTexCoord2f(1.0,1.0); glVertex3f(1.0,  1.0,  0.0)
		glTexCoord2f(0.0,1.0); glVertex3f(0.0, 1.0,  0.0)

		glEnd()

class ZBillboard(Billboard):

	def __init__(self,filename=""):
		Billboard.__init__(self)
		self.image = Image.open(filename)
		self.data = self.image.tostring("raw","R",0,-1)
		self.make()
	
	def draw(self):

		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 

		self.texture()
		
		glDrawPixels(			self.image.size[0],			self.image.size[1],			GL_DEPTH_COMPONENT,			GL_UNSIGNED_BYTE,			self.data,		)
		
		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
	
class ImageBillboard(Billboard):

	def __init__(self,filename=""):
		Billboard.__init__(self)
		self.image = Image.open(filename)
		self.make()
		
	def draw(self):

		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) # GL_NEAREST
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, self.decalmode)

		self.texture()

		glBegin(GL_QUADS)
		glTexCoord2f(0.0,0.0); glVertex3f(0.0, 0.0, 0.0)
		glTexCoord2f(1.0,0.0); glVertex3f(1.0,  0.0, 0.0)
		glTexCoord2f(1.0,1.0); glVertex3f(1.0,  1.0,  0.0)
		glTexCoord2f(0.0,1.0); glVertex3f(0.0, 1.0,  0.0)

		glEnd()	


# här blev det knas innan för att jag gav jättekonstiga glTexCoord med stora tal
# det blev ju fint, kanske göra nån mer gång mer med mening?
class BridgeBillboard(ImageBillboard):

	def __init__(self,filename, height=0.1, offset = 0, softness = 0.0):
	
		self.height = height
		self.offset = offset
		self.softness = softness
		
		ImageBillboard.__init__(self,filename)
		
	def draw(self):
	
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) # GL_LINEAR
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, self.decalmode)

		self.texture()
		vertOffsets = map(lambda x: (x+1)/2.0, [-self.height, self.height])
		texOffsets = vector(vertOffsets) + vector([self.offset, self.offset])
		softOffsets = texOffsets + vector([-self.softness, self.softness])

		glBegin(GL_QUADS)
		
		glTexCoord2f(0.0,softOffsets[0]); glVertex3f(0.0, 0.0, 0.0)
		glTexCoord2f(1.0,softOffsets[0]); glVertex3f(1.0, 0.0, 0.0)
		glTexCoord2f(1.0,softOffsets[0]); glVertex3f(1.0, vertOffsets[0]-self.height/(1-self.softness), 0.0)
		glTexCoord2f(0.0,softOffsets[0]); glVertex3f(0.0, vertOffsets[0]-self.height/(1-self.softness), 0.0)
		
		glTexCoord2f(0.0,softOffsets[0]); glVertex3f(0.0,vertOffsets[0]-self.height/(1-self.softness), 0.0)
		glTexCoord2f(1.0,softOffsets[0]); glVertex3f(1.0,vertOffsets[0]-self.height/(1-self.softness), 0.0)
		glTexCoord2f(1.0,texOffsets[0]); glVertex3f(1.0,vertOffsets[0], 0.0)
		glTexCoord2f(0.0,texOffsets[0]); glVertex3f(0.0,vertOffsets[0], 0.0)
		
		glTexCoord2f(0.0,texOffsets[0]); glVertex3f(0.0, vertOffsets[0], 0.0)
		glTexCoord2f(1.0,texOffsets[0]); glVertex3f(1.0, vertOffsets[0], 0.0)
		glTexCoord2f(1.0,texOffsets[1]); glVertex3f(1.0, vertOffsets[1], 0.0)
		glTexCoord2f(0.0,texOffsets[1]); glVertex3f(0.0, vertOffsets[1], 0.0)
		
		glTexCoord2f(0.0,texOffsets[1]); glVertex3f(0.0,vertOffsets[1], 0.0)
		glTexCoord2f(1.0,texOffsets[1]); glVertex3f(1.0,vertOffsets[1], 0.0)
		glTexCoord2f(1.0,softOffsets[1]); glVertex3f(1.0,vertOffsets[1]+self.height/(1-self.softness), 0.0)
		glTexCoord2f(0.0,softOffsets[1]); glVertex3f(0.0,vertOffsets[1]+self.height/(1-self.softness), 0.0)
		
		glTexCoord2f(0.0,softOffsets[1]); glVertex3f(0.0, vertOffsets[1]+self.height/(1-self.softness), 0.0)
		glTexCoord2f(1.0,softOffsets[1]); glVertex3f(1.0, vertOffsets[1]+self.height/(1-self.softness), 0.0)
		glTexCoord2f(1.0,softOffsets[1]); glVertex3f(1.0, 1.0, 0.0)
		glTexCoord2f(0.0,softOffsets[1]); glVertex3f(0.0, 1.0, 0.0)

		glEnd()
			
class TTFBillboard(Billboard):

	def __init__(self, text, typeface, size,texsize=512):
		Billboard.__init__(self,texsize)

		import ImageFont, ImageDraw

		font = ImageFont.truetype(typeface,self.size*size/200)

		draw = ImageDraw.Draw(self.image)
		for i in range(0, randint(2,8)):
			draw.text((randint(0, self.size/4), randint(-self.size/2, self.size/2)), text, font=font)

		self.make()
		
class TextBillboard(Billboard):

	def __init__(self, text, typeface, size,texsize=512):
		Billboard.__init__(self,texsize)

class GLPlayer(Player):
    def __init__(self, width, height):
        assert Image
        Player.__init__(self)
        self.width = width
        self.height = height
        self.image = Image.new('RGB', (width, height), 0)
        self.size = (width,)
        self.row = 0
        self.inited = 0

    def display(self):
        map = self.automaton.map
        for x in range(map.length):
            self.image.putpixel((x, self.row), (255*map.get((x,)),255*map.get((x,)),255*map.get((x,))))
        self.row += 1

    def main(self, automaton):
        Player.main(self, automaton)
        assert self.automaton is not None
        assert self.automaton.map.dimension == 1 ###
        while self.row < self.height and self.automaton.running():
            self.display()
            self.automaton.update()
            self.automaton.between()
        self.finish()

    def finish(self):
    #   self.image.show("modified show..", "eog")
		return

class CABillboard(Billboard):

	def __init__(self,rule=""):

		Billboard.__init__(self)

		if rule == "":
			rule = randint(1,255)

		player = None
		try:
			player = GLPlayer(self.size,self.size)
			automaton = LinearCodedAutomaton(player.size, rule)
			rightMostAddress = player.size[0] - 1,
			if 1:
				initializer = RandomInitializer()
			else:
				initializer = PointInitializer(rightMostAddress)
			initializer.initialize(automaton)
			player.main(automaton)
		finally:
			if player is not None:
#				player.done()
				self.image = player.image
				self.make()

class RecreatingCubeRecreator(threading.Thread):

	def __init__(self,nrsides):
		self.nrsides = nrsides
	#	threading.Thread.__init__(self)		# uncomment for threading!!!

	# todo, make .append loop
	def recreate(self):
		tempsides = [self.newside() for a in range(self.nrsides)]
		self.newsides = [tempsides[a%self.nrsides] for a in range(6)]
	
	def newside(self):
		return TTFBillboard("visuals: krute.com", "register.ttf",9)

	def run(self):
		print("Generating new patterns...")
		self.recreate()		

class RecreatingCube:
	
	def __init__(self,regenerator=RecreatingCubeRecreator,nrsides=6):
	
		self.regenerator = regenerator
		self.nrsides = nrsides
		self.threaded = False	# change this for threading!!!
		
		if self.threaded == True:
	#	if 0:
			self.recreateThread = self.regenerator(self.nrsides)
			self.recreateThread.start()
			self.recreateThread.join()
	
			self.sides = self.recreateThread.newsides
			self.exchanged = False
		
		else:
			self.fakethread = self.regenerator(self.nrsides)
			self.fakethread.run()
			self.sides = self.fakethread.newsides
			self.exchanged = True
		
	def recreate(self):
	
		if self.threaded == True:
	#	if 0:	
			self.exchanged = False	
			self.recreateThread = self.regenerator()
			self.recreateThread.start()
			self.recreateThread.join()
		
		else:
			self.exchanged = False
			self.fakethread.run()

	def update(self):
		if self.regenerator == True:
	#	if 0:
			if not self.recreateThread.isAlive() and self.recreateThread.newsides != "" and self.exchanged == False:
				self.sides = self.recreateThread.newsides
				print("done!\n")
				self.exchanged = True
		else:
			if self.exchanged == False:
				self.sides = self.fakethread.newsides
				self.exchanged = True

	def permutate(self, perm_no):
		newsides = []
		for i in range(len(self.sides)):
			newsides.append(self.sides[(i+perm_no) % len(self.sides)])
			
		self.sides = newsides

	def draw(self):
	
		self.update()

		glPushMatrix()
	#	glTranslatef(0,0,1)
		glRotatef(0, 0,1,0)
		self.sides[0].draw()
		glPopMatrix()
		
		glPushMatrix()
	#	glTranslatef(1,0,0)	
		glRotatef(90, 0,1,0)
		self.sides[1].draw()
		glPopMatrix()

		glPushMatrix()
		glTranslatef(0,0,-1)
	#	glRotatef(180, 0,1,0)
		self.sides[2].draw()
		glPopMatrix()

		glPushMatrix()
		glTranslatef(1,0,0)
		glRotatef(90, 0,1,0)
		self.sides[3].draw()
		glPopMatrix()

		glPushMatrix()
		glTranslatef(0,1,0)
		glRotatef(-90, 1,0,0)
		self.sides[4].draw()
		glPopMatrix()

		glPushMatrix()
	#	glTranslatef(0,-1,0)
		glRotatef(-90, 1,0,0)
		self.sides[5].draw()
		glPopMatrix()
	
